package com.example.client_demo.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.example.client_demo.common.AOuthConfig;
import com.example.client_demo.common.Clear;
import com.example.client_demo.entity.OUser;
import com.example.client_demo.entity.UserInfo;
import com.example.client_demo.mapper.OUserMapper;
import com.example.client_demo.service.OUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.UUID;

/**
 * @Description:
 * @Author: mayc
 * @Date: 2019/03/14 13:41
 */
@Controller
public class AOuth2Controller {

    private static final String app_id = "48336344535c4288a22fbc00bd5a0de0";
    private static final String app_secret = "48336344535c4288a22fbc00bd5a0de0";
    private static final String redirect_url = "http://192.168.5.234:14323/oauth2/redirect";
    private static final String get_token_url = "http://192.168.5.234:14321/oauth/token";
    private static final String user_info_url = "http://192.168.5.234:14321/user/info";

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private OUserMapper oUserMapper;
    @Autowired
    private OUserService oUserService;

    @Clear
    @RequestMapping(value = "/oauth2/redirect",method = RequestMethod.GET)
    public ModelAndView getDianDaAccessToken(@RequestParam String code, HttpServletRequest request) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, String> params= new LinkedMultiValueMap<>();
        params.add("grant_type","authorization_code");
        params.add("code",code);
        params.add("app_id",app_id);
        params.add("app_secret", app_secret);
        params.add("redirect_uri", redirect_url);
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(get_token_url, requestEntity, String.class);
        String token = response.getBody();
        System.out.println("token:{"+token+"}");
        System.out.println("我拿到token了，我现在要用token获取人员信息，如果获取到，我就让获取到的人员直接登录系统");

        ModelAndView mav = new ModelAndView("login");
        /**返回的token为json格式数据**/
        if (!StringUtils.isEmpty(token)) {
            JSONObject jsonObject = JSON.parseObject(token);
            String accessToken = jsonObject.getString("access_token");
            String tokenType = jsonObject.getString("token_type");
            String expiresIn = jsonObject.getString("expires_in");
            String scope = jsonObject.getString("scope");
            MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>(4);
            multiValueMap.add("access_token", accessToken);
            multiValueMap.add("token_type", tokenType);
            multiValueMap.add("expires_in", expiresIn);
            multiValueMap.add("scope", scope);
            HttpEntity<MultiValueMap<String, Object>> reqEntity = new HttpEntity<>(multiValueMap, headers);
            ResponseEntity<String> resp = restTemplate.postForEntity(user_info_url, reqEntity, String.class);
            String userInfo = resp.getBody();
            System.out.println("获取到的人员信息为："+userInfo);
            System.out.println("我现在拿到人员信息了，现在就可以在后台直接让他登录，并跳转到相关页面去");

            OUser oUser = new OUser();
            oUser.setId(UUID.randomUUID().toString());
            oUser.setAccessToken(accessToken);
            oUser.setTokenType(tokenType);
            oUser.setExpiresIn(expiresIn);
            oUser.setScope(scope);

            if (StringUtils.isEmpty(userInfo)) { // 如果没拿到人员信息，就跳转到登录页
                return mav;
            } else {
                // 拿到人员信息了，做相关验证处理，验证通过后，就直接让其登录
                JSONObject userInfoJson = JSON.parseObject(userInfo);
                String result = userInfoJson.getString("result");
                Integer resCode = userInfoJson.getInteger("code");
                if ("true".equals(result) && resCode == 0) {
                    JSONObject userData = userInfoJson.getJSONObject("data");
                    HttpSession session = request.getSession();
                    session.setAttribute("user_info", userData.getString("userName"));
                    mav = new ModelAndView("main");
                    oUser.setUserAccount(userData.getString("userName"));
                    oUser.setNickName(userData.getString("nickName"));
                    oUser.setPhone(userData.getString("phone"));
                    oUser.setEmail(userData.getString("email"));
                }
            }

            // 保存人员的accessToken
            if (!oUserService.hasStore(accessToken)) {
                oUserMapper.insertOUser(oUser);
            }

        }
        return mav;
    }

    /**
     * 从电大系统访问该接口，请求参数accestoken，
     * 在本地根据该accessToken请求授权服务器，获取人员信息，
     * 然后再根据accessToken和用户账户查询本地缓存的accessToken,两个进行匹配，如果能够匹配，直接登录
     * @param request
     * @param response
     * @return
     * @throws IOException
     */
    @Clear
    @RequestMapping(value = "verify2", method = RequestMethod.GET)
    public ModelAndView loginVerifyFromAOuth2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        ModelAndView mav;
        String accessToken = request.getParameter("accessToken");
        String tokenType = request.getParameter("tokenType");
        String expiresIn = request.getParameter("expiresIn");
        String scope = request.getParameter("scope");

        // 先从电大认证服务器获取人员信息
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        MultiValueMap<String, Object> multiValueMap = new LinkedMultiValueMap<>(4);
        multiValueMap.add("access_token", accessToken);
        multiValueMap.add("token_type", tokenType);
        multiValueMap.add("expires_in", expiresIn);
        multiValueMap.add("scope", scope);
        HttpEntity<MultiValueMap<String, Object>> reqEntity = new HttpEntity<>(multiValueMap, headers);
        ResponseEntity<String> resp = restTemplate.postForEntity(user_info_url, reqEntity, String.class);
        String userInfo = resp.getBody();
        if (StringUtils.isEmpty(userInfo)) {
            mav = new ModelAndView("login");
            return mav;
        }
        JSONObject userInfoJson = JSON.parseObject(userInfo);
        String result = userInfoJson.getString("result");
        Integer resCode = userInfoJson.getInteger("code");
        String userAccount = "";
        if ("true".equals(result) && resCode == 0) {
            userAccount = userInfoJson.getJSONObject("data").getString("userName");
        }

        // 再从本地根据accessToken获取人员信息
        OUser oUser = oUserService.getByAccessToken(accessToken);
        if (oUser == null) {
            mav = new ModelAndView("login");
            return mav;
        }

        // 判断账号是一致
        if (userAccount.equals(oUser.getUserAccount()) && tokenType.equals(oUser.getTokenType())) {
            mav = new ModelAndView("main");
            HttpSession session = request.getSession();
            session.setAttribute("user_info", oUser.getAccessToken());
            return mav;
        }
        return null;
    }

    @RequestMapping(value = "/mytest", method = RequestMethod.GET)
    public String test(String code, HttpServletRequest request) {
        System.out.println("测试的code值："+code);
        return code;
    }

}
